package face.pay.profit.strategy;

import com.alibaba.fastjson.JSON;
import face.pay.constant.OrderType;
import face.pay.dao.*;
import face.pay.entity.*;
import face.pay.profit.UserProfitBiz;
import face.pay.profit.core.RelationInfo;
import face.pay.profit.core.RelationType;
import face.pay.util.MathUtil;
import face.pay.vo.ProfitUser;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * 默认策略 按等级 （级差） 和对应的 结算价（结算件差异）
 * 向上分润到一级用户
 */
@Slf4j
@Component
public class DefaultProfitStrategy extends AbstractProfitStrategy {

    @Autowired
    OrderInfoDao orderInfoDao;

    @Autowired
    IncomeInfoDao incomeInfoDao;

    @Autowired
    EnterpriseInfoDao enterpriseInfoDao;


    @Autowired
    UserInfoDao userInfoDao;

    @Autowired
    UserProfitBiz userProfitBiz;

    @Autowired
    UserAccountDao userAccountDao;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void profit(OrderInfo orderInfo) throws Exception {

        log.info("DEFAULT 分润方式");

        Integer userId = orderInfo.getUserId();
        Long orderId = orderInfo.getId();

        RelationInfo relationInfo =  userProfitBiz.getUserRelation(userId);

        if(relationInfo!=null){

            log.info("成功获取商家-代理关系");

            /**
             * 验证 opendId 绑定情况
             */
            OemInfo oemInfo =  relationInfo.getOemInfo();

            String appId = oemInfo.getAppId();

            String mchId = oemInfo.getMchId();

            List<IncomeInfo> incomeInfos = new ArrayList<>();

            
            Long actFee = orderInfo.getActFee();

            Integer enterprise_userId = orderInfo.getUserId();

            Integer oemId = orderInfo.getOemId();

            EnterpriseInfo enterpriseInfo = this.enterpriseInfoDao.queryByUserId(enterprise_userId);

            String  subMachId =enterpriseInfo.getWxSubMchId();

            /**
             * 商户自己
             */
            ProfitUser mch_user = relationInfo.get(RelationType.MCH_USER);


            Double rate = new Double(0);
            String orderType = orderInfo.getType();
            log.info("订单类型 "+orderType);
            if(OrderType.ALIPAY.equals(orderType)){

                rate =  enterpriseInfo.getAliFinalRate()==null?new Double(0):enterpriseInfo.getAliFinalRate();

            }else if(OrderType.WECHAT.equals(orderType)){
                rate =  enterpriseInfo.getWxFinalRate()==null?new Double(0):enterpriseInfo.getWxFinalRate();

            }
            log.info("商家费率 "+rate);

            if(rate>new Double("0.2") &&  rate<= new Double("0.6") ){

                Long totalMoney =  Long.parseLong("0");


                Double mch_user_consumeProfit = mch_user.getMchConsumeProfit();

                Long mch_consumeFree = MathUtil.profit(actFee,mch_user_consumeProfit);


                /**
                 * 商户自己分润
                 */

                if(mch_consumeFree.compareTo( new Long(0))==1){

                    totalMoney = MathUtil.add(totalMoney,mch_consumeFree);

                    IncomeInfo mch_incomeInfo =  new IncomeInfo( mch_user.getUserId(),oemId,mch_consumeFree,IncomeInfo.TYPE.CONSUME, orderId,actFee);

                    incomeInfos.add(mch_incomeInfo);
                }


                Double enterprise_rate =   new BigDecimal(new Double(rate).toString()).divide(new BigDecimal("100")).doubleValue();

                ProfitUser agencyProfitUser = relationInfo.get(RelationType.AGENCY_USER);

                addAgencyIncomeInfo(orderId,userId,actFee,totalMoney,enterprise_rate,incomeInfos,relationInfo,agencyProfitUser);

                addAllParAgencyIncomeInfo(orderId,userId,actFee,incomeInfos,relationInfo,agencyProfitUser);

                addOemIncomeInfo(orderId,userId,actFee,incomeInfos,relationInfo);

                batchSaveIncome(incomeInfos);

                orderInfo.setProfitSign(1);

                this.orderInfoDao.updateProfitSign(orderInfo);


            }else {
                log.error("商户 费率设置 限制 分佣终止");
            }



        }else {
            log.error("获取商户分佣层级关系失败,分佣终止");

        }

    }


    private void addOemIncomeInfo(Long orderId,Integer mchUserId, Long actFee, List<IncomeInfo> incomeInfos, RelationInfo relationInfo) {

        ProfitUser oemUser = relationInfo.get(RelationType.OEM_USER);

        ProfitUser leveUser = relationInfo.get(RelationType.AGENCY_LEVEL_USER_1);

        if(leveUser==null){//没有一级 取二级
            leveUser = relationInfo.get(RelationType.AGENCY_LEVEL_USER_2);
            if(leveUser==null){//没有二级取三级
                leveUser = relationInfo.get(RelationType.AGENCY_LEVEL_USER_3);
            }if(leveUser==null){
                leveUser = relationInfo.get(RelationType.AGENCY_LEVEL_USER_4);
            }if(leveUser==null){
                leveUser = relationInfo.get(RelationType.AGENCY_LEVEL_USER_5);
            }if(leveUser==null){
                leveUser = relationInfo.get(RelationType.AGENCY_LEVEL_USER_6);
            }if(leveUser==null){
                leveUser = relationInfo.get(RelationType.AGENCY_LEVEL_USER_7);
            }if(leveUser==null){
                leveUser = relationInfo.get(RelationType.AGENCY_LEVEL_USER_8);
            }if(leveUser==null){
                leveUser = relationInfo.get(RelationType.AGENCY_LEVEL_USER_9);
            }
        }
        if(leveUser==null){
            return;
        }

        /**
         * 第一等级 结算价 减去 0.2% 为 oem 该笔订单的利润
         */
        Double profit = MathUtil.sub(leveUser.getConsumeProfit(),  Double.parseDouble("0.002"));

        Long consumeFree = MathUtil.profit(actFee,profit);

        if(consumeFree.compareTo( new Long(0))==1){

            IncomeInfo recincomeInfo =  new IncomeInfo(oemUser.getUserId(),oemUser.getOemId(),consumeFree,IncomeInfo.TYPE.CONSUME, orderId,actFee);
            recincomeInfo.setSrcUserId(mchUserId);
            incomeInfos.add(recincomeInfo);
        }


    }

    public void addAgencyIncomeInfo(Long orderId,Integer mchUserId, Long actFee,Long totalMoney,Double enterprise_rate,  List<IncomeInfo> incomeInfos,RelationInfo relationInfo,ProfitUser agencyProfit) throws Exception {
        Double agency_consumeProfit = agencyProfit.getConsumeProfit();

        Double a_profit = MathUtil.sub(enterprise_rate,agency_consumeProfit);


        Long agency_consumeFee = MathUtil.profit(actFee,a_profit);

        agency_consumeFee = MathUtil.sub(agency_consumeFee.toString(),totalMoney.toString());

        if(agency_consumeFee.compareTo( new Long(0))==1){

            IncomeInfo agencyIncomeInfo =  new IncomeInfo(agencyProfit.getUserId(),agencyProfit.getOemId(),agency_consumeFee,IncomeInfo.TYPE.CONSUME, orderId,actFee);

            agencyIncomeInfo.setSrcUserId(mchUserId);
            /**
             * 未删除的用户
             */
            if(new Integer(0).equals(agencyProfit.getDeleted())){
                incomeInfos.add(agencyIncomeInfo);
            }


        }else if(agency_consumeFee.compareTo( new Long(0))==-1){

            /**
             * 代理商留给商家分润超限 设置不合理  此次分佣终止
             */
            log.error("代理商留给商家分润超限 设置不合理  此次分佣终止");
            throw  new Exception("代理商留给商家分润超限 设置不合理  此次分佣终止");
        }
    }

    /**
     * 代理商所有 父级别 分佣
     * @param incomeInfos
     * @param relationInfo
     * @return
     */
    private void addAllParAgencyIncomeInfo(Long orderId,Integer mchUserId, Long actFee,List<IncomeInfo> incomeInfos,RelationInfo relationInfo,ProfitUser agencyProfit){

        /**
         * agencyProfit 为商户直接代理商 此方法中 不分润
         * 指计算  agencyProfit 所有父级别 分佣
         */
        ProfitUser level9User = addLevelIncome(orderId,mchUserId, agencyProfit.getUserId(), actFee, RelationType.AGENCY_LEVEL_USER_3, incomeInfos, relationInfo, agencyProfit);
        ProfitUser level8User = addLevelIncome(orderId,mchUserId, agencyProfit.getUserId(), actFee, RelationType.AGENCY_LEVEL_USER_3, incomeInfos, relationInfo, level9User);
        ProfitUser level7User = addLevelIncome(orderId,mchUserId, agencyProfit.getUserId(), actFee, RelationType.AGENCY_LEVEL_USER_3, incomeInfos, relationInfo, level8User);
        ProfitUser level6User = addLevelIncome(orderId,mchUserId, agencyProfit.getUserId(), actFee, RelationType.AGENCY_LEVEL_USER_3, incomeInfos, relationInfo, level7User);
        ProfitUser level5User = addLevelIncome(orderId,mchUserId, agencyProfit.getUserId(), actFee, RelationType.AGENCY_LEVEL_USER_3, incomeInfos, relationInfo, level6User);
        ProfitUser level4User = addLevelIncome(orderId,mchUserId, agencyProfit.getUserId(), actFee, RelationType.AGENCY_LEVEL_USER_3, incomeInfos, relationInfo, level5User);
        ProfitUser level3User = addLevelIncome(orderId,mchUserId, agencyProfit.getUserId(), actFee, RelationType.AGENCY_LEVEL_USER_3, incomeInfos, relationInfo, level4User);
        ProfitUser level2User = addLevelIncome(orderId,mchUserId, agencyProfit.getUserId(), actFee, RelationType.AGENCY_LEVEL_USER_2, incomeInfos, relationInfo, level3User);
        ProfitUser level1User = addLevelIncome(orderId,mchUserId, agencyProfit.getUserId(), actFee, RelationType.AGENCY_LEVEL_USER_1, incomeInfos, relationInfo, level2User);

    }


    public ProfitUser addLevelIncome(Long orderId,Integer mchUserId, Integer agencyId,Long actFee,String level_key, List<IncomeInfo> incomeInfos,RelationInfo relationInfo,ProfitUser agencyProfit){

        ProfitUser parProfitUser = agencyProfit;


        ProfitUser agencyLevelProfitUser = relationInfo.get(level_key);

        Integer level = agencyProfit.getLevel();

        Double profit = agencyProfit.getConsumeProfit();

        /**
         * 等级 对应 父级关系存在
         */
        if(agencyLevelProfitUser!=null){

            /**
             * 过滤 父级等级高 level数字越小等级越高 （3>1）
             */
            if(level>agencyLevelProfitUser.getLevel()){

                if(!agencyId.equals(agencyLevelProfitUser.getUserId())){

                    parProfitUser =agencyLevelProfitUser;

                    Double par_consumeProfit = agencyLevelProfitUser.getConsumeProfit();

                    Double p = MathUtil.sub(profit,par_consumeProfit);

                    Long agency_consumeFee = MathUtil.profit(actFee,p);


                    if(agency_consumeFee.compareTo( new Long(0))==1) {
                        IncomeInfo recincomeInfo =  new IncomeInfo(agencyLevelProfitUser.getUserId(),agencyLevelProfitUser.getOemId(),agency_consumeFee,IncomeInfo.TYPE.CONSUME, orderId,actFee);
                        recincomeInfo.setSrcUserId(mchUserId);
                        if(new Integer(0).equals(agencyLevelProfitUser.getDeleted())) {
                            incomeInfos.add(recincomeInfo);
                        }
                    }

                }
            }

        }

        return parProfitUser;
    }

    private void batchSaveIncome(List<IncomeInfo> incomeInfos){
        for(IncomeInfo incomeInfo : incomeInfos){

            this.incomeInfoDao.insert(incomeInfo);

            userAccountDao.addMoney(incomeInfo.getOemId(),incomeInfo.getUserId(),incomeInfo.getMoney());
            /**
             * 零钱入账
             */

        }

    }

}
